package coolapk.cj.cj.utils;

import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zss
 * @created 2021-12-31 19:36
 * @description el表达式工具类，用于解析JsonObject
 */
public class SpelExpressionUtils {
    /**
     * spel解析器
     */
    private static final SpelExpressionParser parser= new SpelExpressionParser();

    /**
     * spel缓存
     */
    private static final ConcurrentHashMap<String, Expression> expressionMap = new ConcurrentHashMap<>(256);

    /**
     * 从缓存中获取spel编译表达式
     *
     * @return              SpelExpression
     */
    public static Expression getExpression(String el) {
        Expression expression = expressionMap.get(el);

        if (expression != null) {
            return expression;
        }

        return expressionMap.computeIfAbsent(el, k -> parser.parseRaw(el));
    }

    /**
     * 获取配置了MapAccessor的context
     * @param root
     * @return
     */
    public static StandardEvaluationContext getContext(Object root) {
        StandardEvaluationContext context = new StandardEvaluationContext(root);
        //这里很关键，如果没有配置MapAccessor，那么只能用['c']['a']这种解析方式
        context.addPropertyAccessor(new MapAccessor());
        return context;
    }

    /**
     * 通过el表达式解析JSONObject
     * @param el el表达式
     * @param root JSONObject
     * @param resultType 获取的值类型
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T> T getValue(String el, Object root, Class<T> resultType) throws Exception {
        Expression expression = getExpression(el);
        StandardEvaluationContext context = getContext(root);
        return expression.getValue(context,resultType);
    }
}
